package qfcfg

import (
	"encoding/xml"
	"io/ioutil"
	"os"

	"github.com/fsnotify/fsnotify"
	"github.com/qf-tech/qftech-base/pkg/log"
	qflog "github.com/qf-tech/qftech-base/pkg/log"
	"github.com/qf-tech/qftech-base/pkg/qfcrypt"
)

// SConfig def
type SConfig struct {
	XMLName xml.Name `xml:"config"` // 指定最外层的标签为config
	Server  SServer  `xml:"server"` // 读取SServer配置项，并将结果保存到Server变量中
	Client  SClient  `xml:"client"` // 读取SClient配置项，并将结果保存到Client变量中
	Mysql   SMysql   `xml:"mysql"`  // 读取SMysql配置项，并将结果保存到Mysql变量中
	Redis   SRedis   `xml:"redis"`  // 读取SRedis配置项，并将结果保存到Redis变量中
}

// SServer def
type SServer struct {
	IP       string `xml:"ip"`       // 读取ip
	Port     int    `xml:"port"`     // 读取port
	Username string `xml:"username"` // 读取用户名
	Password string `xml:"password"`
	HttpIP   string `xml:"httpip"`
	Httpport int    `xml:"httpport"`
	WebDir   string `xml:"webdir"`
}

// SClient def
type SClient struct {
	ClientID   string   `xml:"clientid"` // 读取clientid
	IP         string   `xml:"ip"`       // 读取ip
	Port       int      `xml:"port"`
	AuthEnable bool     `xml:"auth_enable"`
	ProxyUri   []string `xml:"proxyuri"`
}

// PassWord def
type passWord struct {
	Encrypt bool   `xml:"encrypt"` // 读取encrypt
	Value   string `xml:"value"`   // 读取value
}

// SRedis def
type SRedis struct {
	Host     string   `xml:"host"`     // 读取host
	Port     int      `xml:"port"`     // 读取port
	Password passWord `xml:"password"` // 读取password
}

// SMysql def
type SMysql struct {
	Host     string   `xml:"host"`     // 读取host
	Port     int      `xml:"port"`     // 读取port
	Username string   `xml:"username"` // 读取username
	Password passWord `xml:"password"` // 读取password
	Dbname   string   `xml:"dbname"`   // 读取dbname
}

// ServerConfig export var
var ServerConfig SConfig

// decryptPassWord def
func decryptPassWord(pwd *passWord, note string) error {
	if pwd.Encrypt {
		decData, err := qfcrypt.ConfigAes.Decrypt(pwd.Value, "QFTECH")
		if err != nil {
			log.Sugare.Errorf("%s password decrypt err: %v", note, err)
			return err
		}

		decDataStr := string(decData[:])
		pwd.Value = decDataStr
		log.Sugare.Infof("%s password decrypt succeed, plain data: %s", note, decDataStr)
	}

	return nil
}

// readConfig def
func readConfig(path string) {
	file, err := os.Open(path) // For read access.
	if err != nil {
		qflog.Sugare.Errorf("error: %v", err)
		return
	}
	defer file.Close()
	data, err := ioutil.ReadAll(file)
	if err != nil {
		qflog.Sugare.Errorf("error: %v", err)
		return
	}

	ServerConfig = SConfig{}
	err = xml.Unmarshal(data, &ServerConfig)
	if err != nil {
		qflog.Sugare.Errorf("error: %v", err)
		return
	}

	// 敏感信息解密
	_ = decryptPassWord(&ServerConfig.Mysql.Password, "mysql")
	_ = decryptPassWord(&ServerConfig.Redis.Password, "redis")

	qflog.Sugare.Infof("ip:%s port:%d", ServerConfig.Server.IP, ServerConfig.Server.Port)
}

// InitConfig def
func InitConfig() {
	readConfig("config.xml")

	// 监控文件
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		qflog.Sugare.Errorf("error:", err)
	}
	defer watcher.Close()

	// done := make(chan bool)
	go func() {
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				qflog.Sugare.Infof("event:", event)
				if event.Op&fsnotify.Write == fsnotify.Write {
					qflog.Sugare.Infof("modified file:", event.Name)
					readConfig("config.xml")
				}
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				qflog.Sugare.Errorf("error:", err)
			}
		}
	}()

	err = watcher.Add("config.xml")
	if err != nil {
		qflog.Sugare.Errorf("error:", err)
	}
	// <-done
}
